{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# TF object detection API in Azure Machine Learning\n",
    "\n",
    "This notebook demonstrates how to train an object detection model using Tensorflow Object detection API in Azure Machine Learning service\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "\n",
    "import wget\n",
    "import os\n",
    "\n",
    "from azureml.core import Workspace, Experiment, VERSION\n",
    "from azureml.core.compute import ComputeTarget, AmlCompute\n",
    "from azureml.core.environment import Environment\n",
    "from azureml.train.estimator import Estimator\n",
    "from azureml.core.compute_target import ComputeTargetException\n",
    "from azureml.widgets import RunDetails\n",
    "\n",
    "\n",
    "SUBSCRIPTION_ID = \"\"\n",
    "RESOURCE_GROUP = \"\"\n",
    "WORKSPACE_NAME = \"\"\n",
    "\n",
    "EXP_NAME = 'running-pets'\n",
    "CLUSTER_NAME = \"gpu-cluster\"\n",
    "\n",
    "OBJ_DETECT_URL = \"http://storage.googleapis.com/download.tensorflow.org/models/object_detection\"\n",
    "COCO_TAR_BALL = \"faster_rcnn_resnet101_coco_11_06_2017.tar.gz\"\n",
    "\n",
    "TRAIN_DIR = \"train\"\n",
    "DATA_DIR=\"data\"\n",
    "\n",
    "DATASET_URL=\"https://amlgitsamples.blob.core.windows.net/objectdetection\"\n",
    "DATASET_TAR_BALL=\"petdataset.tar.gz\"\n",
    "\n",
    "\n",
    "os.makedirs(DATA_DIR,exist_ok=True)\n",
    "\n",
    "print(\"SDK version:\", VERSION)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize Workspace\n",
    "\n",
    "Initialize a workspace object from persisted configuration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ws = Workspace(subscription_id = SUBSCRIPTION_ID, \n",
    "               resource_group =RESOURCE_GROUP , \n",
    "               workspace_name = WORKSPACE_NAME\n",
    "              )\n",
    "\n",
    "\n",
    "exp = Experiment(workspace=ws, name=EXP_NAME)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Download  COCO-pretrained Model for Transfer Learning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wget.download(os.path.join(OBJ_DETECT_URL,COCO_TAR_BALL),\n",
    "              out=os.getcwd()\n",
    "             )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!tar -xvf $COCO_TAR_BALL -C data --strip 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Upload dataset and model to blob storage\n",
    "\n",
    "The Oxford-IIIT Pet dataset available in raw format [here](https://www.robots.ox.ac.uk/~vgg/data/pets/). For convinience, it is provided  with the example on TF record file format"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wget.download(os.path.join(DATASET_URL,DATASET_TAR_BALL),\n",
    "              out=os.getcwd()\n",
    "             )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!tar -xvf $DATASET_TAR_BALL -C data --strip 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "datastore = ws.get_default_datastore()\n",
    "ds_reference = datastore.upload('data',\n",
    "                 target_path='pet_dataset',\n",
    "                 overwrite=True,\n",
    "                 show_progress=True)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create or attach Azure ML compute to be used for training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from azureml.core.compute import AmlCompute\n",
    "from azureml.core.compute import ComputeTarget\n",
    "\n",
    "\n",
    "\n",
    "found = False\n",
    "cts = ws.compute_targets\n",
    "if CLUSTER_NAME in cts and cts[CLUSTER_NAME].type == 'AmlCompute':\n",
    "    found = True\n",
    "    print('Found existing compute target.')\n",
    "    compute_target = cts[CLUSTER_NAME]\n",
    "\n",
    "if not found:\n",
    "    print('Creating a new compute target...')\n",
    "    provisioning_config = AmlCompute.provisioning_configuration(vm_size =  \"STANDARD_NC6\",max_nodes = 4)\n",
    "\n",
    "    # Create the cluster.\\n\",\n",
    "    compute_target = ComputeTarget.create(ws, CLUSTER_NAME, provisioning_config)\n",
    "\n",
    "print('Checking cluster status...')\n",
    "compute_target.wait_for_completion(show_output = True, min_node_count = None, timeout_in_minutes = 20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The docker file contains the instructions to install the TF Models. It's provided with the example, if you'd like to build your own.\n",
    "\n",
    "For more information on how to perfrom training with custom images on Azure Machine Learning, you can visit \n",
    "https://github.com/Azure/AzureML-Containers/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "conda_env = Environment(\"running_pet_env\")\n",
    "conda_env.python.user_managed_dependencies = True\n",
    "conda_env.python.interpreter_path = '/opt/miniconda/bin/python'\n",
    "conda_env.docker.base_image='datashinobi/tf_models:0.1'\n",
    "conda_env.docker.enabled=True\n",
    "conda_env.docker.gpu_support=True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create estimator\n",
    "\n",
    "We use Estimator base class here instead of [Tensorflow Estimator](https://docs.microsoft.com/en-us/python/api/azureml-train-core/azureml.train.dnn.tensorflow?view=azure-ml-py) since we install Tensorflow in the custom base image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "script_params = {\n",
    "    '--dataset-path':ds_reference.as_mount(),\n",
    "    '--epochs':100\n",
    "}\n",
    "\n",
    "est = Estimator(source_directory=TRAIN_DIR,\n",
    "                 script_params=script_params,\n",
    "                 compute_target=compute_target,\n",
    "                 entry_script='train.py',\n",
    "                 environment_definition=conda_env\n",
    "               )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Submit Experiment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "run = exp.submit(est)\n",
    "RunDetails(run).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " ##  Monitoring with Tensorboard\n",
    " \n",
    "**This step requires installing locally Tensorflow**,  for more information on tensorboard intergation in Azure Machine Learning \n",
    "https://docs.microsoft.com/bs-latn-ba/azure/machine-learning/service/how-to-monitor-tensorboard\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow\n",
    "from azureml.tensorboard import Tensorboard\n",
    "\n",
    "tb = Tensorboard([run])\n",
    "tb.start()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:amlenv]",
   "language": "python",
   "name": "conda-env-amlenv-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
